package blazeConnection
{
  import blazeConnection.BlazeRequest;
  import blazeConnection.BlazeRequestCollection;
  import mx.messaging.Producer;
  
  import flash.display.MovieClip;
  import flash.display.Sprite;
  import flash.net.Responder;
  import flash.net.registerClassAlias;
  import flash.text.TextFieldAutoSize;
  import flash.utils.describeType;
  
  import mx.collections.ArrayCollection;
  import mx.collections.ArrayList;
  import mx.controls.Alert;
  import mx.controls.Label;
  import mx.core.MovieClipAsset;
  import mx.core.mx_internal;
  import mx.logging.ILogger;
  import mx.logging.Log;
  import mx.logging.LogEventLevel;
  import mx.logging.targets.TraceTarget;
  import mx.messaging.Channel;
  import mx.messaging.ChannelSet;
  import mx.messaging.Consumer;
  import mx.messaging.channels.AMFChannel;
  import mx.messaging.channels.HTTPChannel;
  import mx.messaging.config.ConfigMap;
  import mx.messaging.config.LoaderConfig;
  import mx.messaging.config.ServerConfig;
  import mx.messaging.events.*;
  import mx.messaging.events.MessageEvent;
  import mx.messaging.messages.*;
  import mx.rpc.Fault;
  import mx.rpc.events.FaultEvent;
  import mx.rpc.events.ResultEvent;
  import mx.rpc.remoting.RemoteObject;
  import mx.utils.ObjectProxy;
  
  /**
   * Class responsible for handling requests to the server blaze
   */
  public class BlazeConnection extends Sprite
  {
    private static var POLLING_INTERVAL:int = 3000;
    
    [Bindable]
    private var items:ArrayCollection;
    private var stockMap:Object;
    private var channelSet:ChannelSet = new ChannelSet();
    private var channelSetPolling:ChannelSet = new ChannelSet();
    private var amfChannel:AMFChannel;
    private var amfPolling:AMFChannel;
    public var consumer:Consumer;
    private var channelsDefined:Boolean;
    protected var _controlTimeStamp:Number=0;
	
    protected var _pollingAbortOldMessages:Boolean;
        
    protected var ro : RemoteObject = new RemoteObject;
    protected var core:MovieClip;
    protected var amf_url:String = new String;
    
    protected var _requests:Array = new Array;
    
    private var logger:ILogger = Log.getLogger("blazeConnection.BlazeConnection");    
    
    public function BlazeConnection()
    {
      logger.log(LogEventLevel.INFO, "Blaze Connection Init");              
    }
    
	/**
	 * This function sets the channel by BlazeRequest class
	 * 
	 * @param	channel
	 */
    protected function setupChannel(channel:BlazeRequest):void{
      logger.log(LogEventLevel.INFO, "Setup Channel");          
      logger.log(LogEventLevel.INFO, "Destination : " + channel._destination + channel._subtopic + " Polling : " + channel._usePolling);
      
      channelSet.addChannel(amfChannel);
      if (channel._usePolling) {          
        amfPolling = new AMFChannel();
        amfPolling.uri = amf_url + channel._messageAgent;
        amfPolling.id = channel._serviceId;
        amfPolling.requestTimeout = channel._requestTimeout;
        amfPolling.connectTimeout = channel._connectTimeout;
        amfPolling.addEventListener(ChannelFaultEvent.FAULT, handlePollingChannelFault);
        amfPolling.addEventListener(ChannelEvent.CONNECT, handlePollingChannelConnect);
        amfPolling.addEventListener(ChannelEvent.DISCONNECT, handlePollingChannelDisconnect);
        amfPolling.pollingEnabled = true;
        amfPolling.pollingInterval = POLLING_INTERVAL;        
        channelSetPolling.addChannel(amfPolling);          
        consumer = new Consumer();
		consumer.resubscribeAttempts=channel.reconnectAttemps;
        pollingAbortOldMessages = channel.abortOldMessages;
        consumer.destination = channel._destination;
        consumer.subtopic = channel._subtopic;
        consumer.channelSet = channelSetPolling; 
        consumer.addEventListener(MessageAckEvent.ACKNOWLEDGE, messageHandler);        
        consumer.addEventListener(MessageEvent.MESSAGE, messageHandler);        
        consumer.addEventListener(MessageEvent.RESULT, messageHandler);        
        consumer.subscribe(channel._clientId);        
      }  else {          
        amfChannel = new AMFChannel();
        amfChannel.uri = amf_url + channel._messageAgent;
        amfChannel.id = channel._serviceId;          
        channelSet.addChannel(amfChannel);          
        ro.channelSet = channelSet;
        ro.destination = channel._destination;          
        ro.addEventListener(ResultEvent.RESULT, onResult);
        ro.addEventListener(FaultEvent.FAULT, onFault);          
        amfChannel.requestTimeout = channel._requestTimeout;
        amfChannel.connectTimeout = channel._connectTimeout;          
        amfChannel.addEventListener(ChannelFaultEvent.FAULT, handleChannelFault);
        amfChannel.addEventListener(ChannelEvent.CONNECT, handleChannelConnect);
        amfChannel.addEventListener(ChannelEvent.DISCONNECT, handleChannelDisconnect);
      }      
      channelsDefined = true;
    }
   
	/**
	 * This method asks if there is a defined channel, if there creates a new channel
	 * 
	 * @param	_core
	 * @param	_amf_url
	 */
    protected function init(_core:MovieClip, _amf_url:String):void {          
      if (channelsDefined) {
        logger.log(LogEventLevel.INFO, "initBlaze");      
        registerClases();
      } else {
        logger.log(LogEventLevel.FATAL, "Must SetUpChannels before init the Server");
        throw new Error("Must SetUpChannels before init the Server");
      }
    } 
    
	/**
	 * This method registers the classes necessary to connect with blaze
	 */
    private function registerClases():void {
      logger.log(LogEventLevel.INFO, "Registering classes");
      registerClassAlias("flex.messaging.messages.CommandMessage",CommandMessage);
      registerClassAlias("flex.messaging.messages.RemotingMessage",RemotingMessage);
      registerClassAlias("flex.messaging.messages.AcknowledgeMessage", AcknowledgeMessage);
      registerClassAlias("flex.messaging.messages.ErrorMessage",ErrorMessage);
      registerClassAlias("DSC", CommandMessageExt);
      registerClassAlias("DSK", AcknowledgeMessageExt);
      registerClassAlias("flex.messaging.io.ArrayList", ArrayList);
      registerClassAlias("flex.messaging.config.ConfigMap",ConfigMap);
      registerClassAlias("flex.messaging.io.ArrayCollection",ArrayCollection);
      registerClassAlias("flex.messaging.io.ObjectProxy",ObjectProxy);
      registerClassAlias("flex.messaging.messages.HTTPMessage",HTTPRequestMessage);
      registerClassAlias("flex.messaging.messages.SOAPMessage",SOAPMessage);
      registerClassAlias("flex.messaging.messages.AsyncMessage",AsyncMessage);
      registerClassAlias("DSA", AsyncMessageExt);
      registerClassAlias("flex.messaging.messages.MessagePerformanceInfo", MessagePerformanceInfo);
        
      initLoaderContent();
      
    }
    
	/**
	 * This method loads the configuration of the content.
	 */
    private function initLoaderContent():void {
      logger.log(LogEventLevel.INFO, "initLoaderContent");
      var swfURL:String = core.loaderInfo.url;
      LoaderConfig.mx_internal::_url = core.loaderInfo.url;
      LoaderConfig.mx_internal::_parameters = core.loaderInfo.parameters;

    }
    
    private function displayChannelInfo():void
    {
      //trace("pollingEnabled " + amfChannel.pollingEnabled);
      //trace("pollingInterval " + amfChannel.pollingInterval);
      
    }
    
    protected function handleChannelFault(event:ChannelFaultEvent):void {
		logger.log(LogEventLevel.ERROR, "Handle Channel Fault");
    }    
    
    protected function handleChannelConnect(event:ChannelEvent):void {
		logger.log(LogEventLevel.INFO, "Handle Channel Connect");
    }
    
    protected function handleChannelDisconnect(event:ChannelEvent):void {
		logger.log(LogEventLevel.INFO, "Handle Channel Disconnect");
    }
    
    protected function handlePollingChannelFault(e:ChannelFaultEvent):void {
		logger.log(LogEventLevel.ERROR, "Handle Polling Channel Fault");
    }    
    
    protected function handlePollingChannelConnect(event:ChannelEvent):void {
		logger.log(LogEventLevel.INFO, "Handle Polling Channel Connect");
    }
    
    protected function handlePollingChannelDisconnect(event:ChannelEvent):void {
		logger.log(LogEventLevel.INFO, "Polling Channel Disconnect");
    }
    
	/**
	 * This function calls a method published in blaze.
	 * 
	 * @param	_method
	 * @param	_parameters
	 */
    public function request(_method:String, _parameters:Array):void {
		logger.log(LogEventLevel.INFO, "requesting method - " + _method + " - and this parameters : " + _parameters);
		ro.getOperation(_method).send.apply(null, _parameters);
    }
    
    protected function messageHandler(event:MessageEvent):void 
    {
		logger.log(LogEventLevel.INFO, "Handler");
    }

    protected function onResult(result:ResultEvent):void
    {      
		logger.log(LogEventLevel.INFO, "Response AMF");      
    }  
    
    protected function onFault(fault:FaultEvent):void
    {
		logger.log(LogEventLevel.ERROR, "Error AMF" + fault);
    }

	/**
	 * Gets the value of the attribute pollingAbortOldMessages
	 */
	public function get pollingAbortOldMessages():Boolean
	{
		return _pollingAbortOldMessages;
	}

	/**
	 * Sets the value of the attribute pollingAbortOldMessages
	 */
	public function set pollingAbortOldMessages(value:Boolean):void
	{
		_pollingAbortOldMessages = value;
	}

	/**
	 * Gets the value of the attribute _controlTimeStamp
	 */
	public function get controlTimeStamp():Number
	{
		return _controlTimeStamp;
	}

	/**
	 * Sets the value of the attribute _controlTimeStamp
	 */
	public function set controlTimeStamp(value:Number):void
	{
		_controlTimeStamp = value;
	}
  }
}